package service

import (
	"context"
	"errors"
	"fmt"
	"log"
	"net/http"
	"os"
	"quant/backend/api/router"
	"quant/backend/conf"
	"quant/backend/db"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
)

var (
	ginService *GinService
	ginMutex   sync.Mutex
)

type GinService struct {
	srv *http.Server
	// ctx context.Context
}

func NewGinService() *GinService {
	ginMutex.Lock()
	defer ginMutex.Unlock()

	if ginService == nil {
		ginService = &GinService{}
	}
	return ginService
}

func (m *GinService) Start() (string, error) {
	// m.ctx = context.Background()
	// 关键组件初始化（配置/数据库/定时任务），使用fatalOnError统一处理致命错误
	fatalOnError(conf.Init(), "config init failed")
	fatalOnError(db.Init(), "database init failed")

	// 创建主路由引擎并配置API文档
	r := newApp()

	m.srv = &http.Server{
		Addr:    fmt.Sprintf(":%d", conf.Config.App.Port),
		Handler: r.Handler(),
	}
	// 启动HTTP服务器，端口来自应用配置
	var err error
	go func() {
		if err = m.srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			logrus.Errorf("Gin服务启动失败: %t\n", err)
			logrus.Errorf("Gin服务启动出现错误: %s\n", err)
		}
	}()
	if err != nil {
		return "", err
	}
	return "Gin服务启动成功!", nil
}

func (m *GinService) Stop() (string, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	// 关闭 HTTP Server
	// 5秒内优雅关闭服务（将未处理完的请求处理完再关闭服务），超过5秒就超时退出
	if err := m.srv.Shutdown(ctx); err != nil {
		log.Println("Gin服务关闭出现错误:", err)
		return "", err
	}
	log.Println("Gin服务关闭成功!")
	return "Gin服务关闭成功!", nil
}

func newApp() *gin.Engine {
	r := gin.New()
	gin.SetMode(gin.ReleaseMode)
	router.InitRoutes(r)
	return r
}

// 统一处理致命错误
func fatalOnError(err error, msg string) {
	if err != nil {
		logrus.WithError(err).Fatal(msg)
		os.Exit(1) // 保留 os.Exit 确保 go test 等场景能正确捕获退出码
	}
}
